/*
 * hw01serv.c
 *
 *  Created on: Mar 29, 2012
 *      Author: Lee. y. g.
 */


#include	"unp.h"

typedef struct CountInfo {
	uint32_t byte_count;
	uint32_t word_count;
	uint32_t line_count;
}_CountInfo;

void getWordCount(const char* data, _CountInfo* cInfo, size_t maxlen);

void
sig_chld(int signo)
{
	pid_t	pid;
	int		stat;

	while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0)
		printf("child %d terminated\n", pid);
	return;
}

void
word_count(int sockfd)
{

	ssize_t	n;
	char		buf[MAXLINE];
	_CountInfo countInfo;
	pid_t pid;

	pid = getpid();
	countInfo.byte_count = 0;
	countInfo.word_count = 0;
	countInfo.line_count = 0;

	while (1){
		n = readline(sockfd, buf, MAXLINE);
		if((n==2 && buf[0] == '.') || n==0){
			err_msg("------ result -------");
			err_msg("  byte count : %d", countInfo.byte_count);
			err_msg("  word count : %d", countInfo.word_count);
			err_msg("  line count : %d", countInfo.line_count);
			err_msg("---------------------");

			Writen(sockfd, &countInfo, sizeof(_CountInfo));

			break;
		}
		getWordCount(buf,&countInfo, n);
		buf[n-1] = 0;
		err_msg("%d : %s",pid, buf);
	}
}

void getWordCount(const char* data, _CountInfo* cInfo, size_t maxlen){
	uint32_t count = 0;
	uint32_t i;

	for(i=0; i<maxlen; i++) {
		if(data[i] == ' ' || data[i] == '\t'|| data[i] == '\n'){
			count++;
		}
	}

	cInfo->line_count++;
	cInfo->byte_count += i;
	cInfo->word_count += count;
}

/*
void getWordCount(const char* data, _CountInfo* cInfo, size_t maxlen){
	uint32_t count = 0;
	uint32_t i;

	for(i=0; i<maxlen; i++) {
		if(data[i] == ' ' || data[i] == '\t'|| data[i] == '\n'){
			count++;
		}

		if(maxlen >1 && data[i] == '\n') {
			cInfo->line_count++;
			cInfo->byte_count--;
		}
	}

	cInfo->byte_count += i;
	cInfo->word_count += count;
}
*/

int
main(int argc, char **argv)
{
	int					listenfd, connfd;
	pid_t				childpid;
	socklen_t			clilen;
	struct sockaddr_in	cliaddr, servaddr;
	void				sig_chld(int);
	const int on = 1;

	err_msg("Server start!!");

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);
	Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

	Listen(listenfd, LISTENQ);

	Signal(SIGCHLD, sig_chld);	/* must call waitpid() */

	for ( ; ; ) {
		clilen = sizeof(cliaddr);
		if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
			if (errno == EINTR)
				continue;		/* back to for() */
			else
				err_sys("accept error");
		}

		if ( (childpid = Fork()) == 0) {	/* child process */
			Close(listenfd);	/* close listening socket */
			word_count(connfd);	/* process the request */
			exit(0);
		}
		Close(connfd);			/* parent closes connected socket */
	}
}
